package dev.ideas.funkyj.function;

import dev.ideas.funkyj.tuple.Pair;
import dev.ideas.funkyj.tuple.Single;

/**
 */
public abstract class F2<X1, X2, Y> extends F<Pair<? extends X1, ? extends X2>, Y> {
    @Deprecated /*better use a named function*/ protected F2() { }
    protected F2(String string) { super(string); }

    public abstract Y apply(X1 x1, X2 x2);

  public final Y apply(Pair<? extends X1, ? extends X2> pair) { return apply(pair.first(), pair.second()); }

  //todo is it a good idea? maybe change with to something else
  public <Y1, Y2> F3<X1, X2, Y1, Y2> with(final F2<Y, Y1, Y2> function2) {
    return new F3<X1, X2, Y1, Y2>() {
      @Override public Y2 apply(X1 x1, X2 x2, Y1 y1) {
        return function2.apply(F2.this.apply(x1, x2), y1);
      }
    };
  }

  //todo is good idea?
  //todo think of better name, make tests, show usages
  public F<X2, Y> with(final X1 context) {
    return new F<X2, Y>() {
      public Y apply(X2 x2) {
        return F2.this.apply(context, x2);
      }
    };
  }

  public Y of(X1 x1, X2 x2) { return super.of(Pair.of(x1, x2)); }
}